#include <exception>
#include <iostream>

int Division(int a, int b)
{
   if (b == 0) {
      throw std::invalid_argument("division by zero!");
      //throw std::exception();
   }
   return a / b;
}

class Widget
{
public:
   Widget() {
      std::cout << "Widget()" << std::endl;
   }

   ~Widget() {
      std::cout << "~Widget()" << std::endl;
   }
};

class MyException : public std::exception
{
public:
   const char* what() const noexcept {
      return "ready to delete...";
   }
};

int main()
{
   try {
      int res = Division(10, 5);
      std::cout << "res = " << res << std::endl;
   }
   catch (std::invalid_argument& e) {
      std::cout << "invalid argument exception throwed" << std::endl;
      std::cerr << e.what() << std::endl;
   }
   catch (std::exception& e) {
      std::cout << "std::exception throwed" << std::endl;
      std::cerr << e.what() << std::endl;
   }
   catch (...) {}

   //try {
   //   int *p = new int[10000000000];
   //}
   //catch (std::bad_alloc& ba) {
   //   std::cerr << "bad_alloc catched:" << ba.what() << std::endl;
   //}

   try {
      Widget *p = new Widget();
      throw "throw a exception before delete";
      delete p;
   }
   catch (const char* e) {
      std::cerr << e << std::endl;
   }

   return 0;
}
